package com.apes.fn.scm.merchant.disbursement.service;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.fico.debitnote.model.BusinessDebitNote;
import com.apes.fn.fico.debitnote.repository.BusinessDebitNoteRepository;
import com.apes.fn.scm.merchant.account.model.MerchantAccountSettlement;
import com.apes.fn.scm.merchant.account.model.MerchantBankAccount;
import com.apes.fn.scm.merchant.account.repository.AccountSettlementRepository;
import com.apes.fn.scm.merchant.account.repository.MerchantBankAccountRepository;
import com.apes.fn.scm.merchant.disbursement.model.Disbursement;
import com.apes.fn.scm.merchant.disbursement.model.DisbursementItem;
import com.apes.fn.scm.merchant.disbursement.repository.DisbursementItemRepository;
import com.apes.fn.scm.merchant.disbursement.repository.DisbursementRepository;
import com.apes.fn.scm.merchant.disbursement.utils.ConditionUtil;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.Tools;
import com.apes.scm.account.account.repository.CooperationRepository;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.finance.model.BankAccount;
import com.apes.scm.masterdata.finance.repository.BankAccountRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.settle.payment.model.Payment;
import com.apes.scm.settle.payment.model.PaymentRegister;
import com.apes.scm.settle.payment.model.PaymentRegisterItem;
import com.apes.scm.settle.payment.repository.PaymentRegisterRepository;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static java.util.stream.Collectors.toList;

/**
 * @BelongsProject: apes-server
 * @BelongsPackage: com.apes.fn.scm.merchant.disbursement.service
 * @ClassName: DisbursementService
 * @Author: cyy
 * @Description: 排款单业务层
 * @CreateTime: 2023/2/08 11:10
 * @Version: 1.0
 */
@Service("disbursementService")
public class DisbursementService extends DomainService {
    @Autowired
    private DisbursementRepository disbursementRepository;
    @Autowired
    private DisbursementItemRepository disbursementItemRepository;
    @Autowired
    private EntityManager entityManager;
    @Autowired
    private AccountSettlementRepository accountSettlementRepository;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private EnumerationRepository enumerationRepository;
    @Autowired
    private MerchantBankAccountRepository merchantBankAccountRepository;
    @Autowired
    private CooperationRepository cooperationRepository;
    @Autowired
    private DeptRepository deptRepository;
    @Autowired
    private PaymentRegisterRepository paymentRegisterRepository;
    @Autowired
    private BankAccountRepository bankAccountRepository;
    @Autowired
    private BusinessDebitNoteRepository businessDebitNoteRepository;

    /***
     * 创建
     * @param request
     * @return
     */
    public Disbursement create(SimpleRequest request) {
        //        Disbursement disbursement = request.getO(Disbursement.class);
        JSONObject jsonObject = request.getJO();
        JSONArray disbursementItems = jsonObject.getJSONArray("disbursementItems");
        disbursementItems.forEach(disbursementItemJa -> {
            JSONObject disbursementItemJo = (JSONObject)disbursementItemJa;
            disbursementItemJo.forEach((k,v) -> {
                if("".equals(v)) v = null;
                disbursementItemJo.put(k,v);
            });
        });
        Disbursement disbursement = Tools.map(jsonObject, Disbursement.class);
        if(disbursement.getDisbursementItems().size() == 0 )throw new RuntimeException("明细为空请勾选明细");
        disbursement.getDisbursementItems().forEach(disbursementItem -> {
            DisbursementItem history;
            if("merchantAccount".equals(disbursementItem.getBusinessType())){
                MerchantAccountSettlement settlement = accountSettlementRepository.findOne(disbursementItem.getOrderId());
                if (!ObjectUtils.isEmpty(settlement)){
                    disbursementItem.setBusinessDate(settlement.getReconcileDate());
                }
                history = disbursementItemRepository.findHistory(disbursementItem.getMerchantAccountSettlement().getId(), disbursementItem.getMerchantBankAccount().getId());
                if(history != null) throw new RuntimeException ("对账单: " + history.getMerchantAccountSettlement().getId() + "已存在未审核排款单,排款单号: " + history.getDisbursement().getId());
            } else {
                //设置预支单创建日期到排款明细业务日期
                BusinessDebitNote businessDebitNote = businessDebitNoteRepository.findOne(disbursementItem.getOrderId());
                if (!ObjectUtils.isEmpty(businessDebitNote)){
                    disbursementItem.setBusinessDate(businessDebitNote.getCreateDate());
                }
                history = disbursementItemRepository.findByBusinessDebitNote(disbursementItem.getBusinessDebitNote().getId());
                if(history != null) throw new RuntimeException ("预支单: " + history.getBusinessDebitNote().getId() + "已存在未审核排款单,排款单号: " + history.getDisbursement().getId());
            }
            if(disbursementItem.getDisbursementAmount() > disbursementItem.getPayableAmount() - disbursementItem.getDisbursementAlreadyAmount()) throw new RuntimeException("本次排款金额不能大于应付款金额减已排款金额");
        });
        disbursement.setState("create");
        disbursement.setCreator(request.getPersonId());
        //计算已排款金额
        calculationAmount(disbursement.getDisbursementItems(),true);
        return disbursementRepository.saveAndFlush(disbursement);
    }

    /***
     * 编辑
     * @param request
     * @return
     */
    public Disbursement update(SimpleRequest request) {
        Disbursement disbursement = request.getO(Disbursement.class);
        if(disbursement.getDisbursementItems().size() == 0 )throw new RuntimeException("明细为空请勾选明细");
        Disbursement oldDisbursement = disbursementRepository.findOne(disbursement.getId());
        calculationAmount(oldDisbursement.getDisbursementItems(),false);
        calculationAmount(disbursement.getDisbursementItems(),true);
        return disbursementRepository.saveAndFlush(disbursement);
    }

    /***
     * 申请
     */
    public Disbursement apply(SimpleRequest request) {
        Disbursement disbursement = request.getO(Disbursement.class);
        disbursement.setState("apply");
        disbursement.setApplyId(this.getPerson(request));
        disbursement.setApplyDate(new Date());
        Disbursement flush = disbursementRepository.saveAndFlush(disbursement);
        return flush;
    }

    /***
     * OA操作
     */
    public Disbursement applyOA(SimpleRequest request){
        List<Map> mapList = request.get("disbursementItems");
        Disbursement disbursement = request.getO(Disbursement.class);
        Disbursement oldDisbursement = disbursementRepository.findOne(disbursement.getId());
        if("0".equals(request.get("wf_variable_wf_state"))) return oldDisbursement;
        //获取勾选明细id
        List<Object> list = mapList.stream().filter(map -> (Boolean) map.get("selected")).map(map -> map.get("id")).collect(toList());
        //获取勾选行
        List<DisbursementItem> disbursementItemList = disbursement.getDisbursementItems().stream().filter(disbursementItem -> list.contains(disbursementItem.getId())).collect(toList());
        //重新计算本次排款金额
        calculationAmount(oldDisbursement.getDisbursementItems(),false);
        calculationAmount(disbursementItemList,true);
        //重新保存明细
        disbursement.setDisbursementItems(disbursementItemList);
        Disbursement saveAndFlush = disbursementRepository.saveAndFlush(disbursement);
        saveAndFlush.setWrite(false);
        return saveAndFlush;
    }

    /***
     * 审核
     */
    public Disbursement approve(SimpleRequest request) {
        Disbursement oldDisbursement = request.getO(Disbursement.class);
        Disbursement disbursement = disbursementRepository.findOne(oldDisbursement.getId());
        disbursement.setState("approve");
        disbursement.setApproveId(this.getPerson(request));
        disbursement.setApproveDate(new Date());
        disbursement.getDisbursementItems().forEach(this::createPaymentRegister);
        Disbursement saveAndFlush = disbursementRepository.saveAndFlush(disbursement);
        saveAndFlush.setWrite(false);
        return saveAndFlush;
    }

    /***
     * 审核拒绝
     */
    public Disbursement refuse(SimpleRequest request) {
        Disbursement oldDisbursement = request.getO(Disbursement.class);
        Disbursement disbursement = disbursementRepository.findOne(oldDisbursement.getId());
        disbursement.setState("create");
        disbursement.setApplyId(null);
        disbursement.setApplyDate(null);
        return disbursementRepository.saveAndFlush(disbursement);
    }

    /***
     * 删除
     */
    public Disbursement delete(SimpleRequest request) {
        Disbursement oldDisbursement = request.getO(Disbursement.class);
        Disbursement disbursement = disbursementRepository.findOne(oldDisbursement.getId());
        disbursement.setState("delete");
        calculationAmount(disbursement.getDisbursementItems(),false);
        return disbursementRepository.saveAndFlush(disbursement);
    }

    /***
     * 创建付款单
     */
    public void createPaymentRegister(DisbursementItem disbursementItem) {
        PaymentRegister paymentRegister = new PaymentRegister();
        Disbursement disbursement = disbursementItem.getDisbursement();
        PartyRole approveId = disbursement.getApproveId();
        //付款登记金额
        paymentRegister.setAmount(disbursementItem.getDisbursementAmount());
        //创建人
        paymentRegister.set_creator(approveId);
        //审核人
        paymentRegister.setApproveUID(approveId);
        //公司编码
        paymentRegister.setCompany(disbursement.getPlatformCompany());
        //合作方式编码
        paymentRegister.setCooperation(cooperationRepository.findOne("distribution"));
        //部门编码
        paymentRegister.setDept(deptRepository.findByDeptTypeIdAndCompanyId("000006", disbursement.getPlatformCompany().getId()));
        //业务伙伴编码
        paymentRegister.setPartner(disbursementItem.getMerchant());
        //源单据
        paymentRegister.setOriginBusinessName("disbursement");
        //源单号
        paymentRegister.setOrigin(disbursementItem.getId());
        //类型
        paymentRegister.setType("Company");
        //备注
        paymentRegister.setNote("付"+DateUtil.format(disbursementItem.getReconcileBeginDate(),DateUtil.SHOW_DATE_FORMAT)
                +" - "+DateUtil.format(disbursementItem.getReconcileEndDate(),DateUtil.SHOW_DATE_FORMAT)
                +"'"+disbursementItem.getDept().getName()+"'营业款");

        Set<PaymentRegisterItem> paymentRegisterItemSet = new HashSet<>();
        PaymentRegisterItem paymentRegisterItem = new PaymentRegisterItem();
        double disbursementAmount = disbursementItem.getDisbursementAmount();
        //应付款金额
        paymentRegisterItem.setPayableAmount(disbursementAmount);
        //付款金额
        paymentRegisterItem.setAmount(disbursementAmount);
        //收款账户
        if(disbursementItem.getBankAccount() == null) throw new RuntimeException(disbursement.getId() +" 明细："+ disbursementItem.getId() + "没有银行账户");
        paymentRegister.setAccountBank(disbursementItem.getBankAccount().getAccountName());
        //开户行
        paymentRegister.setBank(disbursementItem.getBankAccount().getBank().getName());
        //开户行号
        paymentRegister.setBankAccount(disbursementItem.getBankAccount().getAccountId());
        //支行
        paymentRegister.setSubbranch(disbursementItem.getBankAccount().getBankBranch());
        if("merchantAccount".equals(disbursementItem.getBusinessType())){
            //源单号
            paymentRegisterItem.setOrigin(disbursementItem.getMerchantAccountSettlement().getId());
            //源单据
            paymentRegisterItem.setOriginBusinessType("merchantSettlement");
        } else {
            //源单号
            paymentRegisterItem.setOrigin(disbursementItem.getBusinessDebitNote().getId());
            //源单据
            paymentRegisterItem.setOriginBusinessType("businessDebitNote");
        }
        paymentRegisterItemSet.add(paymentRegisterItem);
        paymentRegister.setPaymentRegisterItem(paymentRegisterItemSet);
        this.invoke("disbursement.paymentRegister.approveByDisbursement", this.invoke("disbursement.paymentRegister.createByDisbursement", paymentRegister));
    }

    /***
     * 计算本次排款金额
     */
    public void calculationAmount(List<DisbursementItem> disbursementItems,boolean sign){
        //本次排款金额写入银行账户已排款金额
        disbursementItems.forEach(disbursementItem -> {
            if("merchantAccount".equals(disbursementItem.getBusinessType())){
                MerchantBankAccount merchantBankAccount = merchantBankAccountRepository.findOne(disbursementItem.getMerchantBankAccount().getId());
                double amount;
                double disbursementAmount = disbursementItem.getDisbursementAmount();
                if(sign){
                    amount = disbursementItem.getDisbursementAlreadyAmount() + disbursementAmount;
                } else {
                    amount = merchantBankAccount.getDisbursementAlreadyAmount() - disbursementAmount;
                }
                merchantBankAccount.setDisbursementAlreadyAmount(amount);
            } else {
                BusinessDebitNote businessDebitNote = businessDebitNoteRepository.findOne(disbursementItem.getBusinessDebitNote().getId());
                double amount;
                double disbursementAmount = disbursementItem.getDisbursementAmount();
                if(sign){
                    amount = disbursementItem.getDisbursementAlreadyAmount() + disbursementAmount;
                } else {
                    amount = businessDebitNote.getDisbursementAlreadyAmount() - disbursementAmount;
                }
                businessDebitNote.setDisbursementAlreadyAmount(amount);
                if(!"pay".equals(businessDebitNote.getState())){
                    if(businessDebitNote.getDisbursementAlreadyAmount() == 0 ){
                        businessDebitNote.setState("pending");
                    }else{
                        businessDebitNote.setState("arrangement");
                    }
                }
            }
        });
        //根据对账单分组
        Map<String, List<DisbursementItem>> collect = disbursementItems.stream().filter(disbursementItem -> "merchantAccount".equals(disbursementItem.getBusinessType()))
                .collect(Collectors.groupingBy(disbursementItem -> disbursementItem.getMerchantAccountSettlement().getId()));
        if(collect.isEmpty()) return;
        //本次排款金额写入对账单总计已排款金额
        collect.forEach((merchantAccountSettlement,disbursementItemList)-> {
            MerchantAccountSettlement settlement = accountSettlementRepository.findOne(merchantAccountSettlement);
            double amount;
            double sumDisbursementAmount = disbursementItemList.stream().mapToDouble(DisbursementItem::getDisbursementAmount).sum();
            if(sign){
                amount = sumDisbursementAmount + settlement.getTotalDisbursementAlreadyAmount();
            } else {
                amount = settlement.getTotalDisbursementAlreadyAmount() - sumDisbursementAmount;
            }
            settlement.setTotalDisbursementAlreadyAmount(amount);
            //已有部分付款则不变更2.0状态
            if(!"pay".equals(settlement.getState())){
                if(settlement.getTotalDisbursementAlreadyAmount() == 0 ){
                    settlement.setState("pending");
                }else{
                    settlement.setState("arrangement");
                }
            }
        });
    }

    /***
     * 查询未排款的赋能结算对账单
     */
    public List getMerchantAccountSettlement(SimpleRequest request) {
        JSONObject jsonObject = request.getJO();
        String platformCompanyId = jsonObject.get("platformCompanyId").toString();
        String reconcileBeginDateFormat = "";
        if(jsonObject.get("reconcileBeginDate") != null) reconcileBeginDateFormat = DateUtil.format(DateUtil.parse(jsonObject.get("reconcileBeginDate").toString()), "yyyy-MM-dd");
        String reconcileEndDateFormat = "";
        if(jsonObject.get("reconcileEndDate") != null){
            Date reconcileEndDate = DateUtil.add(DateUtil.parse(jsonObject.get("reconcileEndDate").toString()),Calendar.DATE,1);
            reconcileEndDateFormat = DateUtil.format(reconcileEndDate, "yyyy-MM-dd");
        }
        //平台公司
        String platformCompanyIdSql = Objects.nonNull(platformCompanyId) ? " AND C.COMPANY_ID = '" + platformCompanyId + "'" : " AND 1 = 1 ";
        //对账单结算期起
        String reconcileBeginDateSql = "".equals(reconcileBeginDateFormat) ? " AND 1 = 1 " : " AND A.RECONCILE_BEGIN_DATE >= to_date('" + reconcileBeginDateFormat + "','yyyy-MM-dd') ";
        String borrowingDateSql = "".equals(reconcileBeginDateFormat) ? " AND 1 = 1 " : " AND A.BORROWING_DATE >= to_date('" + reconcileBeginDateFormat + "','yyyy-MM-dd') ";
        //对账单结算期止
        String reconcileEndDateSql = "".equals(reconcileEndDateFormat) ? " AND 1 = 1 " : " AND A.RECONCILE_END_DATE < to_date('" + reconcileEndDateFormat + "','yyyy-MM-dd') ";
        String limitDateSql = "".equals(reconcileEndDateFormat) ? " AND 1 = 1 " : " AND A.LIMIT_DATE < to_date('" + reconcileEndDateFormat + "','yyyy-MM-dd') ";
        StringBuffer sSql = new StringBuffer();
        sSql.append("SELECT A.* " +
                    "    FROM (SELECT DISTINCT A.ID ORDER_ID, A.MERCHANT_ID, B.DISBURSEMENT_ALREADY_AMOUNT, " +
                    "            TO_DATE(TO_CHAR(A.RECONCILE_BEGIN_DATE, " +
                    "                    'yyyy/mm/dd hh24:mi:ss'), " +
                    "                    'yyyy/mm/dd hh24:mi:ss') RECONCILE_BEGIN_DATE, " +
                    "            TO_DATE(TO_CHAR(A.RECONCILE_END_DATE, 'yyyy/mm/dd hh24:mi:ss'), " +
                    "                    'yyyy/mm/dd hh24:mi:ss') RECONCILE_END_DATE, " +
                    "            A.FN_TAG, A.STATE STATE, " +
                    "            (SELECT T.ID " +
                    "            FROM MAS_DEPT T, MAS_STORE E " +
                    "            WHERE E.DEPT_ID = T.ID " +
                    "           AND T.DEPT_TYPE = '000007' " +
                    "            AND T.COMPANY_ID = A.MERCHANT_ID " +
                    "            AND ROWNUM = 1) DEPT_ID, " +
                    "            TO_DATE(TO_CHAR(A.FINANCIAL_AUDIT_DATE, " +
                    "                    'yyyy/mm/dd hh24:mi:ss'), " +
                    "                    'yyyy/mm/dd hh24:mi:ss') FINANCIAL_AUDIT_DATE, " +
                    "            TO_DATE(TO_CHAR(A.MERCHANT_CONFIRMATION_DATE, " +
                    "                    'yyyy/mm/dd hh24:mi:ss'), " +
                    "                    'yyyy/mm/dd hh24:mi:ss') MERCHANT_CONFIRMATION_DATE, " +
                    "            B.ID MERCHANT_BANK_ACCOUNT_ID, B.AMOUNT PAYABLE_AMOUNT, " +
                    "            A.RECONCILE_UID RECONCILE_ID, 'merchantAccount' TYPE " +
                    "    FROM MERCHANT_ACCOUNT_SETTLEMENT A, MERCHANT_BANK_ACCOUNT B, " +
                    "            FN_CONTRACT C " +
                    "    WHERE A.ID = B.MERCHANT_SETTLEMENT_ID " +
                    "    AND C.PARTNER_ID = A.MERCHANT_ID " +
                    "    AND C.VALID_PERIOD > TRUNC(A.RECONCILE_BEGIN_DATE) " +
                    "   AND C.STATE = 'approve' " +
                    "    AND A.STATE in ('pending', 'arrangement', 'pay') " +
                    "    AND (B.AMOUNT - B.DISBURSEMENT_ALREADY_AMOUNT) > 0 " + platformCompanyIdSql + reconcileBeginDateSql + reconcileEndDateSql + " " +
                    "    AND A.SETTLE_BUSINESS_MONEY_TOTAL > 0 " +
                    "    UNION ALL " +
                    "    SELECT A.ID ORDER_ID, A.FN_CUSTOMER_ID MERCHANT_ID, " +
                    "            NVL(A.DISBURSEMENT_ALREADY_AMOUNT,0), " +
                    "            TO_DATE(TO_CHAR(A.BORROWING_DATE, 'yyyy/mm/dd hh24:mi:ss'), " +
                    "                    'yyyy/mm/dd hh24:mi:ss') RECONCILE_BEGIN_DATE, " +
                    "            TO_DATE(TO_CHAR(A.LIMIT_DATE, 'yyyy/mm/dd hh24:mi:ss'), " +
                    "                    'yyyy/mm/dd hh24:mi:ss') RECONCILE_END_DATE, " +
                    "            A.FN_TAG, A.STATE STATE, " +
                    "            A.DEPT_ID, " +
                    "            TO_DATE(TO_CHAR(A.APPROVE_DATE, 'yyyy/mm/dd hh24:mi:ss'), " +
                    "                    'yyyy/mm/dd hh24:mi:ss') FINANCIAL_AUDIT_DATE, " +
                    "            TO_DATE(TO_CHAR(A.APPROVE_DATE, 'yyyy/mm/dd hh24:mi:ss'), " +
                    "                    'yyyy/mm/dd hh24:mi:ss') MERCHANT_CONFIRMATION_DATE, " +
                    "            A.BANK_ACCOUNT_ID MERCHANT_BANK_ACCOUNT_ID, " +
                    "            A.CAPITAL_BALANCE PAYABLE_AMOUNT, ' ' RECONCILE_ID, " +
                    "            'businessDebitNote' TYPE " +
                    "    FROM FN_BUSINESS_DEBIT_NOTE A, FN_CONTRACT C " +
                    "    WHERE C.PARTNER_ID = A.FN_CUSTOMER_ID " +
                    "    AND C.VALID_PERIOD > TRUNC(A.BORROWING_DATE) " +
                    "   AND C.STATE = 'approve' " +
                    "    AND A.STATE in ('pending', 'arrangement', 'pay') " +
                    "    AND (A.CAPITAL_BALANCE - NVL(A.DISBURSEMENT_ALREADY_AMOUNT,0)) > 0 " + platformCompanyIdSql + borrowingDateSql + limitDateSql + ") A " +
                    "    ORDER BY CASE A.TYPE " +
                    "    WHEN 'merchantAccount' THEN " +
                    "    1 " +
                    "    WHEN 'businessDebitNote' THEN " +
                    "    2 " +
                    "    END, CASE A.FN_TAG " +
                    "    WHEN '001906' THEN " +
                    "    1 " +
                    "    WHEN '001907' THEN " +
                    "    2 " +
                    "    WHEN '002005' THEN " +
                    "    3 " +
                    "    WHEN '001905' THEN " +
                    "    4 " +
                    "    END ASC, A.MERCHANT_ID");
        Query query = entityManager.createNativeQuery(sSql.toString());
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        if(query.getResultList().size() == 0) throw new RuntimeException("未查询到结果");
        List<Map<String, Object>> listMap;
        listMap = query.getResultList();
        listMap.forEach(map -> {
            //商户
            Map<String, Object> merchant = partyRoleRepository.findIdAndName(map.get("MERCHANT_ID").toString());
            map.put("merchant",merchant);
            map.put("merchantName",merchant.get("name"));
            //部门
            Map<String, Object> dept = deptRepository.findIdAndName(map.get("DEPT_ID").toString());
            map.put("deptName",dept.get("name"));
            map.put("dept",dept);
            //赋能标签
            if(map.get("FN_TAG") == null) throw new RuntimeException("部门: "+dept.get("name")+" 查询不到赋能标签");
            Map<String, Object> fnTag = enumerationRepository.findIdAndName(map.get("FN_TAG").toString());
            map.put("fnTag",fnTag);
            map.put("fnTagName",fnTag.get("description"));
            if("merchantAccount".equals(map.get("TYPE"))){
                //业务单号
                map.put("merchantAccountSettlement",accountSettlementRepository.findIdAndName(map.get("ORDER_ID").toString()));
                //对账单银行账户
                MerchantBankAccount merchantBankAccount = merchantBankAccountRepository.findOne(map.get("MERCHANT_BANK_ACCOUNT_ID").toString());
                map.put("merchantBankAccount",MapUtil.mapper("id",merchantBankAccount.getId(),"name",merchantBankAccount.getName()));
                //银行账户
                BankAccount bankAccount = merchantBankAccount.getAccountId();
                map.put("bankAccount",MapUtil.mapper("id",bankAccount.getId(),"accountName",bankAccount.getAccountName()));
                map.put("MERCHANT_BANK_ACCOUNT_ID",merchantBankAccount.getAccountId().getId());
                map.put("bankAccountName",merchantBankAccount.getAccountId().getAccountName());
                //对账人
                Map<String, Object> reconcileId = partyRoleRepository.findIdAndName(map.get("RECONCILE_ID").toString());
                map.put("reconcileId",reconcileId);
                map.put("reconcileIdName",reconcileId.get("name"));
            } else {
                //业务单号
                map.put("businessDebitNote",businessDebitNoteRepository.findIdAndName(map.get("ORDER_ID").toString()));
                //银行账户
                Map<String, Object> bankAccount = bankAccountRepository.findIdAndName(map.get("MERCHANT_BANK_ACCOUNT_ID").toString());
                map.put("bankAccount", bankAccount);
            }
            //单据号
            map.put("orderId",map.get("ORDER_ID"));
            //状态
            map.put("settlementState",map.get("STATE"));
            //类型
            map.put("businessType",map.get("TYPE"));
            //应付款金额
            map.put("payableAmount",map.get("PAYABLE_AMOUNT"));
            //已排款金额
            map.put("disbursementAlreadyAmount",map.get("DISBURSEMENT_ALREADY_AMOUNT"));
            //本次排款金额
            map.put("disbursementAmount",Double.parseDouble(map.get("PAYABLE_AMOUNT").toString()) - Double.parseDouble(map.get("DISBURSEMENT_ALREADY_AMOUNT").toString()));
            //结算期起
            map.put("reconcileBeginDate",DateUtil.format((Date)map.get("RECONCILE_BEGIN_DATE"), "yyyy-MM-dd"));
            //结算期止
            map.put("reconcileEndDate",DateUtil.format((Date)map.get("RECONCILE_END_DATE"), "yyyy-MM-dd"));
            //财务发出日期
            if(map.get("FINANCIAL_AUDIT_DATE") != null) map.put("financialAuditDate",DateUtil.format((Date)map.get("FINANCIAL_AUDIT_DATE"), "yyyy-MM-dd HH:mm:ss"));
            //门店确认日期
            if(map.get("MERCHANT_CONFIRMATION_DATE") != null) map.put("merchantConfirmationDate",DateUtil.format((Date)map.get("MERCHANT_CONFIRMATION_DATE"), "yyyy-MM-dd HH:mm:ss"));
        });
        return listMap;
    }

    public void payRewrite(SimpleRequest request){
        Payment payment = request.getO(Payment.class);
        payment.getPaymentItemSet().forEach(paymentItem -> {
            if ("PaymentRegister".equals(paymentItem.getOriginBusinessType())){
                PaymentRegister paymentRegister = paymentRegisterRepository.findOne(paymentItem.getOrigin());
                if("disbursement".equals(paymentRegister.getOriginBusinessName())){
                    DisbursementItem disbursementItem = disbursementItemRepository.findOne(paymentRegister.getOrigin());
                    disbursementItem.setAmountDate(payment.getApproveDate());
                    disbursementItem.setAlreadyPayAmount(paymentItem.getAmount());
                    disbursementItem.setPayState(true);
                }
            }
        });
    }

    /**
     * 排款单导入
     *
     * @param request
     * @return
     */
    public JSONObject beImport(SimpleRequest request) {
        JSONObject importData = request.get("importData");//Excel信息
        //定义变量
        JSONObject exclObject = new JSONObject();                  //返回值

        JSONArray exclArr = new JSONArray();            //行内容
        importData.forEach((k, v) -> {

            //获得value ===Excel内容
            JSONArray excl = (JSONArray) v;
            JSONArray header = (JSONArray) excl.get(0); //首行数据

            for (int i = 0; i < excl.size(); i++) {  //遍历每一行

                if (i == 0) { //跳过首行
                    exclArr.add(excl.get(i));
                    continue;
                }

                JSONArray lineLong = (JSONArray) excl.get(i); //当前行
                //合并2个list为一个map,KEY为首行数据，Value为当前行数据
                Map<String, Object> map = IntStream.range(0, header.size()).collect(LinkedHashMap<String, Object>::new,
                        (m, key) -> m.put(header.getString(key).replace(";", ""),
                                key >= lineLong.size() ? "" : (lineLong.getString(key) == null ? "" : lineLong.getString(key).trim().replaceAll("[\\s]{2,}", " "))),
                        (m1, m2) -> {
                        });
                if("对账单".equals(map.get("源单据"))){
                    Map settlementAndBank = disbursementRepository.findBySettlementAndBank(map.get("源单号").toString(), map.get("对账单银行账户").toString());
                    if(settlementAndBank.isEmpty()) throw new RuntimeException("请检查对账单号：" + map.get("源单号").toString() + "是否有此对账单银行账户："+map.get("对账单银行账户").toString());
                    MerchantAccountSettlement merchantAccountSettlement = (MerchantAccountSettlement) settlementAndBank.get("merchant");
                    MerchantBankAccount merchantBankAccount = (MerchantBankAccount) settlementAndBank.get("bank");
                    if(merchantAccountSettlement.getFnTag() == null) throw new RuntimeException("第"+i+"行没有赋能标签,请先去门店信息配置");
                    map.put("源单据","merchantAccount");
                    map.put("源单号",merchantAccountSettlement.getId());
                    Dept dept = merchantAccountSettlement.getDept();
                    map.put("部门",MapUtil.mapper("id",dept.getId(),"name",dept.getName()));
                    map.put("结算期起",DateUtil.format(merchantAccountSettlement.getReconcileBeginDate(),DateUtil.SHOW_DATE_FORMAT));
                    map.put("结算期止",DateUtil.format(merchantAccountSettlement.getReconcileEndDate(),DateUtil.SHOW_DATE_FORMAT));
                    Enumeration fnTag = merchantAccountSettlement.getFnTag();
                    map.put("赋能标签",MapUtil.mapper("id",fnTag.getId(),"description",fnTag.getDescription()));
                    BankAccount bankAccount = merchantBankAccount.getAccountId();
                    map.put("付款户名",MapUtil.mapper("id",bankAccount.getId(),"accountName",bankAccount.getAccountName()));
                    double amount = merchantBankAccount.getAmount();
                    double disbursementAlreadyAmount = merchantBankAccount.getDisbursementAlreadyAmount();
                    map.put("应付款金额",amount);
                    map.put("已排款金额",disbursementAlreadyAmount);
                    double disbursementAmount = Double.parseDouble(map.get("本次排款金额").toString());
//                    if(disbursementAmount > amount - disbursementAlreadyAmount || disbursementAmount < 0) throw new RuntimeException("第"+i+"行本次排款金额过大或小于0,请重新输入");
                    PartyRole reconcileUid = merchantAccountSettlement.getReconcileUid();
                    map.put("对账人",MapUtil.mapper("id",reconcileUid.getId(),"name",reconcileUid.getParty().getName()));
                    map.put("财务发出日期",DateUtil.format(merchantAccountSettlement.getFinancialAuditDate(),DateUtil.SHOW_DATETIME_FORMAT));
                    map.put("门店确认日期",DateUtil.format(merchantAccountSettlement.getMerchantConfirmationDate(),DateUtil.SHOW_DATETIME_FORMAT));
                    map.put("状态",merchantAccountSettlement.getState());
                    PartyRole merchant = merchantAccountSettlement.getMerchant();
                    map.put("商户",MapUtil.mapper("id",merchant.getId(),"name",merchant.getName()));
                    map.put("对账单",MapUtil.mapper("id",merchantAccountSettlement.getId()));
                    map.put("预支单","");
                    map.put("对账单银行账户",MapUtil.mapper("id",merchantBankAccount.getId(),"name",merchantBankAccount.getName()));
                    List valueList = new ArrayList<>(map.values());
                    exclArr.add(valueList);
                } else {
                    BusinessDebitNote businessDebitNote = businessDebitNoteRepository.findOne(map.get("源单号").toString());
                    if(businessDebitNote.getFnTag() == null) throw new RuntimeException("第"+i+"行没有赋能标签,请先去门店信息配置");
                    map.put("源单据","businessDebitNote");
                    map.put("源单号",businessDebitNote.getId());
                    Dept saleDept = businessDebitNote.getSaleDept();
                    map.put("部门",MapUtil.mapper("id",saleDept.getId(),"name",saleDept.getName()));
                    map.put("结算期起",DateUtil.format(businessDebitNote.getBorrowingDate(),DateUtil.SHOW_DATE_FORMAT));
                    map.put("结算期止",DateUtil.format(businessDebitNote.getLimitDate(),DateUtil.SHOW_DATE_FORMAT));
                    Enumeration fnTag = businessDebitNote.getFnTag();
                    map.put("赋能标签",MapUtil.mapper("id",fnTag.getId(),"description",fnTag.getDescription()));
                    double amount = businessDebitNote.getCapitalBalance();
                    double disbursementAlreadyAmount = businessDebitNote.getDisbursementAlreadyAmount();
                    BankAccount bankAccount = businessDebitNote.getBankAccount();
                    map.put("付款户名",MapUtil.mapper("id",bankAccount.getId(),"accountName",bankAccount.getAccountName()));
                    map.put("应付款金额",amount);
                    map.put("已排款金额",disbursementAlreadyAmount);
                    double disbursementAmount = Double.parseDouble(map.get("本次排款金额").toString());
//                    if(disbursementAmount > amount - disbursementAlreadyAmount || disbursementAmount < 0) throw new RuntimeException("第"+i+"行本次排款金额过大或小于0,请重新输入");
                    map.put("财务发出日期",DateUtil.format(businessDebitNote.getApproveDate(),DateUtil.SHOW_DATETIME_FORMAT));
                    map.put("门店确认日期",DateUtil.format(businessDebitNote.getApproveDate(),DateUtil.SHOW_DATETIME_FORMAT));
                    map.put("状态",businessDebitNote.getState());
                    PartyRole fnCustomer = businessDebitNote.getFnCustomer();
                    map.put("商户",MapUtil.mapper("id",fnCustomer.getId(),"name",fnCustomer.getName()));
                    map.put("对账单","");
                    map.put("预支单",MapUtil.mapper("id",businessDebitNote.getId()));
                    List valueList = new ArrayList<>(map.values());
                    exclArr.add(valueList);
                }
            }
            exclObject.put(k, exclArr);
        });
        return exclObject;
    }

    private JSONObject progress(SimpleRequest request){
        JSONObject jsonObject = request.getJO();
        JSONArray conditionArray = (JSONArray)jsonObject.get("condition");
        //获取查询条件
        JSONObject jo = getCondition(conditionArray);
        List<Map<String, Object>> list = new LinkedList<>();
        //已确认应付
        List<Map<String, Object>> settleBusinessMoneyTotal = findSettleBusinessMoneyTotal(jo);
        if(settleBusinessMoneyTotal != null) list.addAll(settleBusinessMoneyTotal);
        //已排款金额
        List<Map<String, Object>> disbursementAmount = findDisbursementAmount(jo);
        if(disbursementAmount != null) list.addAll(disbursementAmount);
        //已付款金额
        List<Map<String, Object>> alreadyPayAmount = findAlreadyPayAmount(jo);
        if(alreadyPayAmount != null) list.addAll(alreadyPayAmount);
        return splicingAmount(calculateAmount(list),findBusinessDebitNoteAmount(jo));
    }

    private JSONObject getCondition(JSONArray conditionArray){
        JSONObject jo = new JSONObject();
        conditionArray.stream().forEach(item ->{
            JSONObject json = (JSONObject)item;
            if(json.getString("field").equals("RECONCILE_BEGIN_DATE")){
                if(json.getString("operator").equals("GTE")){
                    //开始
                    jo.put("RECONCILE_BEGIN_DATE_START",DateUtil.format(DateUtil.parse(json.getString("value")), "yyyy-MM-dd"));
                }else {
                    //结束
                    jo.put("RECONCILE_BEGIN_DATE_END",DateUtil.format(DateUtil.parse(json.getString("value")), "yyyy-MM-dd"));
                }
            } else if(json.getString("field").equals("RECONCILE_END_DATE")){
                if(json.getString("operator").equals("GTE")){
                    //开始
                    jo.put("RECONCILE_END_DATE_START",DateUtil.format(DateUtil.parse(json.getString("value")), "yyyy-MM-dd"));
                }else {
                    //结束
                    jo.put("RECONCILE_END_DATE_END",DateUtil.format(DateUtil.parse(json.getString("value")), "yyyy-MM-dd"));
                }
            } else if (json.getString("field").equals("CREATE_DATE")){
                if(json.getString("operator").equals("GTE")){
                    //开始
                    jo.put("CREATE_DATE_START",DateUtil.format(DateUtil.parse(json.getString("value")), "yyyy-MM-dd"));
                }else {
                    //结束
                    jo.put("CREATE_DATE_END",DateUtil.format(DateUtil.parse(json.getString("value")), "yyyy-MM-dd"));
                }
            } else if(json.getString("field").equals("FN_TAG")){
                //赋能标签
                jo.put("FN_TAG",json.getString("value"));
            }
        });
        return jo;
    }

    private List<Map<String, Object>> findSettleBusinessMoneyTotal(JSONObject jo){
        //赋能标签
        String fnTagSql = jo.containsKey("FN_TAG") ? " AND A.FN_TAG = '" + jo.getString("FN_TAG") + "'" : " AND 1 = 1 ";
        //对账日期起
        String reconcileBeginDateStartSql = jo.containsKey("RECONCILE_BEGIN_DATE_START") ? " AND A.RECONCILE_BEGIN_DATE >= to_date('"+jo.getString("RECONCILE_BEGIN_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //对账日期止
        String reconcileBeginDateEndSql = jo.containsKey("RECONCILE_BEGIN_DATE_END") ? " AND A.RECONCILE_BEGIN_DATE <= to_date('"+jo.getString("RECONCILE_BEGIN_DATE_END")+"','yyyy-MM-dd')  " : " AND 1 = 1 ";
        //结束日期起
        String reconcileEndDateStartSql = jo.containsKey("RECONCILE_END_DATE_START") ? " AND A.RECONCILE_END_DATE >= to_date('"+jo.getString("RECONCILE_END_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //结束日期止
        String reconcileEndDateEndSql = jo.containsKey("RECONCILE_END_DATE_END") ? " AND A.RECONCILE_END_DATE <= to_date('"+jo.getString("RECONCILE_END_DATE_END")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //创建日期起
        String createDateStartSql = jo.containsKey("CREATE_DATE_START") ? " AND TRUNC(A.RECONCILE_DATE) >= to_date('"+jo.getString("CREATE_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //创建日期止
        String createDateEndSql = jo.containsKey("CREATE_DATE_END") ? " AND TRUNC(A.RECONCILE_DATE) <= to_date('"+jo.getString("CREATE_DATE_END")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        StringBuffer sSql = new StringBuffer();
        sSql.append("SELECT NVL(SUM(A.SETTLE_BUSINESS_MONEY_TOTAL),0) SETTLE_BUSINESS_MONEY_TOTAL, A.FN_TAG, 'merchantAccount' TYPE " +
                "  FROM MERCHANT_ACCOUNT_SETTLEMENT A" +
                " WHERE A.SETTLE_BUSINESS_MONEY_TOTAL > 0" +
                fnTagSql + reconcileBeginDateStartSql + reconcileBeginDateEndSql + reconcileEndDateStartSql + reconcileEndDateEndSql + createDateStartSql + createDateEndSql +
                "   GROUP BY A.FN_TAG" +
                "   ORDER BY CASE A.FN_TAG " +
                "            WHEN '001906' THEN 1 " +
                "            WHEN '001907' THEN 2 " +
                "            WHEN '002005' THEN 3 " +
                "            WHEN '001905' THEN 4 " +
                "            END " +
                "            ASC ");
        Query query = entityManager.createNativeQuery(sSql.toString());
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        if(query.getResultList().size() == 0) return null;
        List<Map<String, Object>> listMap;
        listMap = query.getResultList();
        return listMap;
    }

    private List<Map<String, Object>> findDisbursementAmount(JSONObject jo){
        //赋能标签
        String fnTagSql = jo.containsKey("FN_TAG") ? " AND B.FN_TAG = '" + jo.getString("FN_TAG") + "'" : " AND 1 = 1 ";
        //对账日期起
        String reconcileBeginDateStartSql = jo.containsKey("RECONCILE_BEGIN_DATE_START") ? " AND B.RECONCILE_BEGIN_DATE >= to_date('"+jo.getString("RECONCILE_BEGIN_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //对账日期止
        String reconcileBeginDateEndSql = jo.containsKey("RECONCILE_BEGIN_DATE_END") ? " AND B.RECONCILE_BEGIN_DATE <= to_date('"+jo.getString("RECONCILE_BEGIN_DATE_END")+"','yyyy-MM-dd')  " : " AND 1 = 1 ";
        //结束日期起
        String reconcileEndDateStartSql = jo.containsKey("RECONCILE_END_DATE_START") ? " AND B.RECONCILE_END_DATE >= to_date('"+jo.getString("RECONCILE_END_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //结束日期止
        String reconcileEndDateEndSql = jo.containsKey("RECONCILE_END_DATE_END") ? " AND B.RECONCILE_END_DATE <= to_date('"+jo.getString("RECONCILE_END_DATE_END")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //创建日期起
        String createDateStartSql = jo.containsKey("CREATE_DATE_START") ? " AND TRUNC(B.BUSINESS_DATE) >= to_date('"+jo.getString("CREATE_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //创建日期止
        String createDateEndSql = jo.containsKey("CREATE_DATE_END") ? " AND TRUNC(B.BUSINESS_DATE) <= to_date('"+jo.getString("CREATE_DATE_END")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        StringBuffer sSql = new StringBuffer();
        sSql.append("SELECT NVL(SUM(B.DISBURSEMENT_AMOUNT),0) DISBURSEMENT_AMOUNT, B.FN_TAG, 'merchantAccount' TYPE " +
                "  FROM FN_MERCHANT_DISBURSEMENT A,FN_MERCHANT_DISBURSEMENT_ITEM B,MERCHANT_ACCOUNT_SETTLEMENT C" +
                " WHERE A.ID = B.DISBURSEMENT_ID" +
                "   AND A.STATE != 'delete'" +
                "   AND B.MERCHANT_ACCOUNT_SETTLEMENT_ID IS NOT NULL" +
                "   AND C.ID = B.MERCHANT_ACCOUNT_SETTLEMENT_ID" +
                fnTagSql + reconcileBeginDateStartSql + reconcileBeginDateEndSql + reconcileEndDateStartSql + reconcileEndDateEndSql + createDateStartSql + createDateEndSql +
                "   GROUP BY B.FN_TAG" +
                "   ORDER BY CASE B.FN_TAG " +
                "            WHEN '001906' THEN 1 " +
                "            WHEN '001907' THEN 2 " +
                "            WHEN '002005' THEN 3 " +
                "            WHEN '001905' THEN 4 " +
                "            END " +
                "            ASC ");
        Query query = entityManager.createNativeQuery(sSql.toString());
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        if(query.getResultList().size() == 0) return null;
        List<Map<String, Object>> listMap;
        listMap = query.getResultList();
        return listMap;
    }

    private List<Map<String, Object>> findAlreadyPayAmount(JSONObject jo){
        //赋能标签
        String fnTagSql = jo.containsKey("FN_TAG") ? " AND B.FN_TAG = '" + jo.getString("FN_TAG") + "'" : " AND 1 = 1 ";
        //对账日期起
        String reconcileBeginDateStartSql = jo.containsKey("RECONCILE_BEGIN_DATE_START") ? " AND B.RECONCILE_BEGIN_DATE >= to_date('"+jo.getString("RECONCILE_BEGIN_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //对账日期止
        String reconcileBeginDateEndSql = jo.containsKey("RECONCILE_BEGIN_DATE_END") ? " AND B.RECONCILE_BEGIN_DATE <= to_date('"+jo.getString("RECONCILE_BEGIN_DATE_END")+"','yyyy-MM-dd')  " : " AND 1 = 1 ";
        //结束日期起
        String reconcileEndDateStartSql = jo.containsKey("RECONCILE_END_DATE_START") ? " AND B.RECONCILE_END_DATE >= to_date('"+jo.getString("RECONCILE_END_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //结束日期止
        String reconcileEndDateEndSql = jo.containsKey("RECONCILE_END_DATE_END") ? " AND B.RECONCILE_END_DATE <= to_date('"+jo.getString("RECONCILE_END_DATE_END")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //创建日期起
        String createDateStartSql = jo.containsKey("CREATE_DATE_START") ? " AND TRUNC(B.BUSINESS_DATE) >= to_date('"+jo.getString("CREATE_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //创建日期止
        String createDateEndSql = jo.containsKey("CREATE_DATE_END") ? " AND TRUNC(B.BUSINESS_DATE) <= to_date('"+jo.getString("CREATE_DATE_END")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        StringBuffer sSql = new StringBuffer();
        sSql.append("SELECT NVL(SUM(B.ALREADY_PAY_AMOUNT),0) ALREADY_PAY_AMOUNT, B.FN_TAG, 'merchantAccount' TYPE " +
                "  FROM FN_MERCHANT_DISBURSEMENT A,FN_MERCHANT_DISBURSEMENT_ITEM B,MERCHANT_ACCOUNT_SETTLEMENT C" +
                " WHERE A.ID = B.DISBURSEMENT_ID" +
                " AND A.STATE != 'delete'" +
                " AND B.MERCHANT_ACCOUNT_SETTLEMENT_ID IS NOT NULL" +
                " AND C.ID = B.MERCHANT_ACCOUNT_SETTLEMENT_ID" +
                fnTagSql + reconcileBeginDateStartSql + reconcileBeginDateEndSql + reconcileEndDateStartSql + reconcileEndDateEndSql + createDateStartSql + createDateEndSql +
                "   GROUP BY B.FN_TAG" +
                "   ORDER BY CASE B.FN_TAG " +
                "            WHEN '001906' THEN 1 " +
                "            WHEN '001907' THEN 2 " +
                "            WHEN '002005' THEN 3 " +
                "            WHEN '001905' THEN 4 " +
                "            END " +
                "            ASC ");
        Query query = entityManager.createNativeQuery(sSql.toString());
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        if(query.getResultList().size() == 0) return null;
        List<Map<String, Object>> listMap;
        listMap = query.getResultList();
        return listMap;
    }

    /**
     * 计算预支单金额
     * @param jo
     * @return
     */
    private List<Map<String, Object>> findBusinessDebitNoteAmount(JSONObject jo){
        //对账日期起
        String reconcileBeginDateStartSql = jo.containsKey("RECONCILE_BEGIN_DATE_START") ? " AND A.RECONCILE_BEGIN_DATE >= to_date('"+jo.getString("RECONCILE_BEGIN_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //对账日期止
        String reconcileBeginDateEndSql = jo.containsKey("RECONCILE_BEGIN_DATE_END") ? " AND A.RECONCILE_BEGIN_DATE <= to_date('"+jo.getString("RECONCILE_BEGIN_DATE_END")+"','yyyy-MM-dd')  " : " AND 1 = 1 ";
        //结束日期起
        String reconcileEndDateStartSql = jo.containsKey("RECONCILE_END_DATE_START") ? " AND A.RECONCILE_END_DATE >= to_date('"+jo.getString("RECONCILE_END_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //结束日期止
        String reconcileEndDateEndSql = jo.containsKey("RECONCILE_END_DATE_END") ? " AND A.RECONCILE_END_DATE <= to_date('"+jo.getString("RECONCILE_END_DATE_END")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //创建日期起
        String createDateStartSql = jo.containsKey("CREATE_DATE_START") ? " AND TRUNC(A.CREATE_DATE) >= to_date('"+jo.getString("CREATE_DATE_START")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        //创建日期止
        String createDateEndSql = jo.containsKey("CREATE_DATE_END") ? " AND TRUNC(A.CREATE_DATE) <= to_date('"+jo.getString("CREATE_DATE_END")+"','yyyy-MM-dd') " : " AND 1 = 1 ";
        StringBuffer sSql= new StringBuffer();
        sSql.append("SELECT SUM(A.SETTLE_BUSINESS_MONEY_TOTAL) SETTLE_BUSINESS_MONEY_TOTAL," +
                "       SUM(A.DISBURSEMENT_AMOUNT) DISBURSEMENT_AMOUNT," +
                "       (SUM(A.SETTLE_BUSINESS_MONEY_TOTAL) - SUM(A.DISBURSEMENT_AMOUNT)) UNPAID_DISBURSEMENT_AMOUNT," +
                "       SUM(A.ALREADY_PAY_AMOUNT) ALREADY_PAY_AMOUNT," +
                "       (SUM(A.DISBURSEMENT_AMOUNT) - SUM(A.ALREADY_PAY_AMOUNT)) UNPAID_AMOUNT," +
                "       '' FN_TAG," +
                "       '' FN_TAG_NAME," +
                "       'businessDebitNote' TYPE," +
                "       '预支单' TYPE_NAME," +
                "       'report/fn.businessDebitPlatform.query' API" +
                "  FROM(SELECT NVL(A.CAPITAL_BALANCE,0) SETTLE_BUSINESS_MONEY_TOTAL," +
                " 0 DISBURSEMENT_AMOUNT," +
                " 0 ALREADY_PAY_AMOUNT," +
                " A.BORROWING_DATE RECONCILE_BEGIN_DATE," +
                " A.LIMIT_DATE RECONCILE_END_DATE," +
                " A.CREATE_DATE CREATE_DATE" +
                "  FROM FN_BUSINESS_DEBIT_NOTE A" +
                " WHERE A.STATE NOT IN ('create','apply','delete')  " +
                "UNION ALL " +
                "SELECT 0 SETTLE_BUSINESS_MONEY_TOTAL," +
                "       B.DISBURSEMENT_AMOUNT DISBURSEMENT_AMOUNT," +
                "       B.ALREADY_PAY_AMOUNT ALREADY_PAY_AMOUNT," +
                "       B.RECONCILE_BEGIN_DATE RECONCILE_BEGIN_DATE," +
                "       B.RECONCILE_END_DATE RECONCILE_END_DATE," +
                "       C.CREATE_DATE CREATE_DATE" +
                "  FROM FN_MERCHANT_DISBURSEMENT A, FN_MERCHANT_DISBURSEMENT_ITEM B,FN_BUSINESS_DEBIT_NOTE C" +
                " WHERE A.ID = B.DISBURSEMENT_ID" +
                "   AND A.STATE != 'delete'" +
                "   AND B.BUSINESS_DEBIT_NOTE_ID IS NOT NULL" +
                "   AND C.ID = B.BUSINESS_DEBIT_NOTE_ID) A" +
                " WHERE 1 = 1" + reconcileBeginDateStartSql + reconcileBeginDateEndSql + reconcileEndDateStartSql + reconcileEndDateEndSql + createDateStartSql + createDateEndSql);
        Query query = entityManager.createNativeQuery(sSql.toString());
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map<String, Object>> listMap;
        listMap = query.getResultList();
        if(listMap.get(0).get("SETTLE_BUSINESS_MONEY_TOTAL") == null && listMap.get(0).get("DISBURSEMENT_AMOUNT") == null && listMap.get(0).get("ALREADY_PAY_AMOUNT") == null) return null;
        return listMap;
    }

    private Map<Object, List<Map<String, Object>>> calculateAmount(List<Map<String, Object>> list){
        if(list == null) return null;
        List<Map<String, Object>> arrayList = new ArrayList<>();
        //根据赋能标签分组
        Map<Object, List<Map<String, Object>>> listMap = list.stream().collect(Collectors.groupingBy(map -> map.get("FN_TAG")));
        listMap.forEach((k,v) -> {
            HashMap<String, Object> unpaidDisbursementAmountMap = new HashMap<>();
            HashMap<String, Object> unpaidAmountMap = new HashMap<>();
            unpaidDisbursementAmountMap.put("FN_TAG",k);
            unpaidDisbursementAmountMap.put("TYPE","merchantAccount");
            unpaidAmountMap.put("FN_TAG",k);
            unpaidAmountMap.put("TYPE","merchantAccount");
            //已确认应付
            double settleBusinessMoneyTotal = v.stream().filter(vMap -> vMap.containsKey("SETTLE_BUSINESS_MONEY_TOTAL")).mapToDouble(vMap -> Double.parseDouble(vMap.get("SETTLE_BUSINESS_MONEY_TOTAL").toString())).sum();
            //已排款金额
            double disbursementAmount = v.stream().filter(vMap -> vMap.containsKey("DISBURSEMENT_AMOUNT")).mapToDouble(vMap -> Double.parseDouble(vMap.get("DISBURSEMENT_AMOUNT").toString())).sum();
            //已付款金额
            double alreadyPayAmount = v.stream().filter(vMap -> vMap.containsKey("ALREADY_PAY_AMOUNT")).mapToDouble(vMap -> Double.parseDouble(vMap.get("ALREADY_PAY_AMOUNT").toString())).sum();
            DecimalFormat decimalFormat = new DecimalFormat();
            decimalFormat.setGroupingUsed(false);
            decimalFormat.setMaximumFractionDigits(2);
            //未排款金额
            String unpaidDisbursementAmount = decimalFormat.format(settleBusinessMoneyTotal - disbursementAmount);
            //未付款金额
            String unpaidAmount = decimalFormat.format(disbursementAmount - alreadyPayAmount);
            unpaidDisbursementAmountMap.put("UNPAID_DISBURSEMENT_AMOUNT",unpaidDisbursementAmount);
            unpaidAmountMap.put("UNPAID_AMOUNT",unpaidAmount);
            arrayList.add(unpaidDisbursementAmountMap);
            arrayList.add(unpaidAmountMap);
        });
        list.addAll(arrayList);
        return list.stream().collect(Collectors.groupingBy(map -> map.get("FN_TAG")));
    }

    private JSONObject splicingAmount(Map<Object, List<Map<String, Object>>> map,List list){
        JSONArray jsonArray = new JSONArray();
        //重新构造数据格式
        map.forEach((k,v) -> {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("FN_TAG",k);
            jsonObject.put("FN_TAG_NAME",enumerationRepository.findOne(k.toString()).getDescription());
            v.forEach(vMap -> {
                jsonObject.put("TYPE",vMap.get("TYPE"));
                jsonObject.put("TYPE_NAME","merchantAccount".equals(vMap.get("TYPE"))?"赋能对账单":"预支单");
                jsonObject.put("API","report/merchant.settle.query");
                //已确认应付
                if(vMap.containsKey("SETTLE_BUSINESS_MONEY_TOTAL")) jsonObject.put("SETTLE_BUSINESS_MONEY_TOTAL",vMap.get("SETTLE_BUSINESS_MONEY_TOTAL").toString());
                //已排款金额
                if(vMap.containsKey("DISBURSEMENT_AMOUNT")) jsonObject.put("DISBURSEMENT_AMOUNT",vMap.get("DISBURSEMENT_AMOUNT").toString());
                //未排款金额
                if(vMap.containsKey("ALREADY_PAY_AMOUNT")) jsonObject.put("ALREADY_PAY_AMOUNT",vMap.get("ALREADY_PAY_AMOUNT").toString());
                //已付款金额
                if(vMap.containsKey("UNPAID_DISBURSEMENT_AMOUNT")) jsonObject.put("UNPAID_DISBURSEMENT_AMOUNT",vMap.get("UNPAID_DISBURSEMENT_AMOUNT").toString());
                //未付款金额
                if(vMap.containsKey("UNPAID_AMOUNT")) jsonObject.put("UNPAID_AMOUNT",vMap.get("UNPAID_AMOUNT").toString());
            });
            jsonArray.add(jsonObject);
        });
        //拼接预支单
        if(list != null) jsonArray.add(JSONObject.toJSON(list.get(0)));
        JSONArray footers = new JSONArray();
        JSONObject footer = new JSONObject();
        DecimalFormat decimalFormat = new DecimalFormat();
        decimalFormat.setGroupingUsed(false);
        decimalFormat.setMaximumFractionDigits(2);
        //拼接底部汇总金额
        footer.put("SETTLE_BUSINESS_MONEY_TOTAL",decimalFormat.format(jsonArray.stream().mapToDouble(jo -> {
            JSONObject jsonObject = (JSONObject) jo;
            return jsonObject.containsKey("SETTLE_BUSINESS_MONEY_TOTAL") ? jsonObject.getDouble("SETTLE_BUSINESS_MONEY_TOTAL") : 0;
        }).sum()));
        footer.put("DISBURSEMENT_AMOUNT",jsonArray.stream().mapToDouble(jo -> {
            JSONObject jsonObject = (JSONObject) jo;
            return jsonObject.containsKey("DISBURSEMENT_AMOUNT") ? jsonObject.getDouble("DISBURSEMENT_AMOUNT") : 0;
        }).sum());
        footer.put("UNPAID_DISBURSEMENT_AMOUNT",jsonArray.stream().mapToDouble(jo -> {
            JSONObject jsonObject = (JSONObject) jo;
            return jsonObject.containsKey("UNPAID_DISBURSEMENT_AMOUNT") ? jsonObject.getDouble("UNPAID_DISBURSEMENT_AMOUNT") : 0;
        }).sum());
        footer.put("ALREADY_PAY_AMOUNT",jsonArray.stream().mapToDouble(jo -> {
            JSONObject jsonObject = (JSONObject) jo;
            return jsonObject.containsKey("ALREADY_PAY_AMOUNT") ? jsonObject.getDouble("ALREADY_PAY_AMOUNT") : 0;
        }).sum());
        footer.put("UNPAID_AMOUNT",jsonArray.stream().mapToDouble(jo -> {
            JSONObject jsonObject = (JSONObject) jo;
            return jsonObject.containsKey("UNPAID_AMOUNT") ? jsonObject.getDouble("UNPAID_AMOUNT") : 0;
        }).sum());
        footers.add(footer);
        JSONObject response = new JSONObject();
        response.put("total", jsonArray.size());
        response.put("pages", 1);
        response.put("size", jsonArray.size());
        response.put("elements", jsonArray.size());
        response.put("content", jsonArray);
        response.put("footer", footers);
        return response;
    }

    /**
     * 根据id返回对账单或预支单路由地址
     * @param simpleRequest
     * @return
     */
    public String settlementOrBusinessDebitNote(SimpleRequest simpleRequest){
        JSONObject requestJO = simpleRequest.getJO();
        String id = requestJO.getString("id");
        //根据id获取对账单
        MerchantAccountSettlement accountSettlement = accountSettlementRepository.findOne(id);
        if (ObjectUtils.isEmpty(accountSettlement)){
            //为空则是预支单
            return "form/fn.businessDebitPlatform";
        }
        //对账单
        return "form/merchant.settlement.form";
    }

    /**
     * 赋能排款查询所有
     * @param request
     * @return
     */
    public JSONObject queryList(SimpleRequest request){
        JSONObject response = new JSONObject();
        PartyRole company = request.getCurrentCompany();
        JSONObject requestJO = request.getJO();
        JSONObject conditions = ConditionUtil.queryConditions(requestJO);
        Page<Disbursement> list = disbursementRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "id", "EQ", conditions.getString("id"),
                "state", "EQ", conditions.getString("state"),
                "createDate", "GTE", conditions.get("createDateStart") == null ? null : conditions.getDate("createDateStart"),
                "createDate", "LTE", conditions.get("createDateEnd") == null ? null : conditions.getDate("createDateEnd"),
                "approveDate", "GTE", conditions.get("approveDateStart") == null ? null : conditions.getDate("approveDateStart"),
                "approveDate", "LTE", conditions.get("approveDateEnd") == null ? null : conditions.getDate("approveDateEnd")
        ), PageRequest.of(requestJO.getInteger("page"), requestJO.getInteger("size"), Sort.by(Sort.Direction.DESC, "id")));
        List<Disbursement> disbursements = list.getContent();
        response.put("total", list.getTotalElements());
        response.put("pages", 1);
        response.put("size", disbursements.size());
        response.put("elements", disbursements.size());
        response.put("content", disbursements);
        return response;
    }

}
